# -*- coding: utf-8 -*-
# 1. 导入需要的工具：FastAPI核心、SQLAlchemy数据库工具、Pydantic请求体校验
import uvicorn
from fastapi import FastAPI, Depends, HTTPException
from sqlalchemy import create_engine, String, Integer, Column, Date, DateTime, DECIMAL  # 新增时间/数值类型
from sqlalchemy.orm import declarative_base, sessionmaker, Session
from typing import Optional, List  # 新增List用于批量返回数据
from starlette.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from datetime import datetime, date  # 新增：用于字符串转日期/时间类型
# 2. 数据库连接配置（请确认你的MySQL用户名、密码、数据库名是否正确）
SQLALCHEMY_DATABASE_URL = "mysql+pymysql://root:123456@localhost:3306/a0804"

# 3. 创建数据库引擎（连接通道）
engine = create_engine(
    SQLALCHEMY_DATABASE_URL,
    pool_pre_ping=True  # 每次请求前检查连接有效性
)

# 4. 创建会话工厂（操作数据库的"手柄"）
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

# 5. 创建模型基类（所有表模型的"模板"）
Base = declarative_base()


# -------------------------- 核心修改1：定义4张学生表的SQLAlchemy模型 --------------------------
# 1. 沃林学生基本信息表（主表）
class 沃林学生基本信息表(Base):
    __tablename__ = "沃林学生基本信息表"  # 与数据库表名完全一致
    学生编号 = Column(Integer, primary_key=True, index=True, autoincrement=True)  # 自增主键
    学生班级 = Column(String(20), index=True)
    学生姓名 = Column(String(20), nullable=False)  # 姓名必填
    籍贯 = Column(String(50))
    毕业院校 = Column(String(100))
    专业 = Column(String(50))
    入学时间 = Column(Date)  # 日期类型（对应MySQL的DATE）
    毕业时间 = Column(Date)
    学历 = Column(String(20))
    顾问编号 = Column(String(20))
    年龄 = Column(Integer, nullable=True)  # 年龄可选
    性别 = Column(String(2))  # 男/女


# 2. 沃林学生考核成绩表（从表，关联基本信息表）
class 沃林学生考核成绩表(Base):
    __tablename__ = "沃林学生考核成绩表"
    成绩ID = Column(Integer, primary_key=True, index=True, autoincrement=True)  # 自增主键
    学生编号 = Column(Integer, index=True)  # 外键字段（关联基本信息表的学生编号）
    考核序次 = Column(String(20))
    分数 = Column(DECIMAL(5, 2))  # 小数类型（5位总长度，2位小数，如92.50）


# 3. 沃林学生考勤记录表（从表，关联基本信息表）
class 沃林学生考勤记录表(Base):
    __tablename__ = "沃林学生考勤记录表"
    考勤ID = Column(Integer, primary_key=True, index=True, autoincrement=True)
    学生编号 = Column(Integer, index=True)  # 外键字段
    考核时间 = Column(DateTime)  # 时间戳类型（对应MySQL的DATETIME，含时分秒）
    补录标记 = Column(String(2))  # 是/否


# 4. 沃林学生就业信息表（从表，关联基本信息表）
class 沃林学生就业信息表(Base):
    __tablename__ = "沃林学生就业信息表"
    就业ID = Column(Integer, primary_key=True, index=True, autoincrement=True)
    学生编号 = Column(Integer, index=True)  # 外键字段
    就业开放时间 = Column(Date)
    OFFER下发时间 = Column(DateTime)
    就业公司名称 = Column(String(100))
    就业薪资 = Column(DECIMAL(10, 2))  # 薪资类型（10位总长度，2位小数，如12000.00）


# -------------------------- 核心修改2：定义Pydantic请求体模型（前端传参校验） --------------------------
# 1. 新增学生基本信息的请求体（必传/可选字段与表模型一致）
class 学生基本信息创建(BaseModel):
    学生班级: str
    学生姓名: str  # 必传
    籍贯: Optional[str] = None  # 可选
    毕业院校: Optional[str] = None
    专业: Optional[str] = None
    入学时间: Optional[date]=None  # 前端传字符串格式（如"2023-09-01"），SQLAlchemy自动转Date
    毕业时间: Optional[date] = None
    学历: Optional[str] = None
    顾问编号: Optional[str] = None
    年龄: Optional[int] = None
    性别: str  # 必传（男/女）

    # 配置：允许返回SQLAlchemy模型对象（否则前端看不到中文字段名）
    class Config:
        orm_mode = True


# 2. 更新学生基本信息的请求体（仅允许更新部分字段）
class 学生基本信息更新(BaseModel):
    学生班级: Optional[str] = None
    籍贯: Optional[str] = None
    毕业院校: Optional[str] = None
    专业: Optional[str] = None
    毕业时间: Optional[date]=None
    学历: Optional[str] = None
    顾问编号: Optional[str] = None
    年龄: Optional[int] = None
    性别: Optional[str] = None

    class Config:
        orm_mode = True


# 3. 新增考核成绩的请求体
class 学生考核成绩创建(BaseModel):
    学生编号: int  # 必传（需关联已存在的学生）
    考核序次: str  # 如"第一次月考"
    分数: float  # 前端传浮点数（如85.5），SQLAlchemy自动转DECIMAL

    class Config:
        orm_mode = True


# 4. 新增考勤记录的请求体
class 学生考勤记录创建(BaseModel):
    学生编号: int
    考核时间: Optional[datetime]=None  # 前端传字符串（如"2023-10-08 09:00:00"），自动转DateTime
    补录标记: str  # 是/否

    class Config:
        orm_mode = True


# 5. 新增就业信息的请求体
class 学生就业信息创建(BaseModel):
    学生编号: int
    就业开放时间: Optional[date]=None  # 如"2024-03-01"
    OFFER下发时间: Optional[datetime]=None  # 如"2024-03-15 10:20:00"
    就业公司名称: str
    就业薪资: float  # 如12000.0

    class Config:
        orm_mode = True


# -------------------------- 数据库会话依赖（复用原逻辑） --------------------------
def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()


# -------------------------- 初始化FastAPI与跨域配置（复用原逻辑） --------------------------
app = FastAPI(title="沃林学生信息管理API", version="1.0")

# 允许的前端地址（根据你的实际前端地址修改）
origins = [
    "http://localhost:63342",  # 常见的VS Code Live Server地址
]

# 跨域配置
app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_methods=["*"],  # 允许所有请求方法（GET/POST/PUT/DELETE）
    allow_headers=["*"],  # 允许所有请求头
)


# -------------------------- 核心修改3：编写4张表的CRUD接口 --------------------------
# ================================= 1. 学生基本信息表接口 =================================
# 1.1 新增学生基本信息
@app.post("/student/basic", tags=["学生基本信息管理"], response_model=学生基本信息创建,summary=["新增学生信息"])
def create_student_basic(
        student: 学生基本信息创建,
        db: Session = Depends(get_db)
):
    # 检查：避免同一班级重复姓名（可根据实际需求调整校验规则）
    db_student = db.query(沃林学生基本信息表).filter(
        沃林学生基本信息表.学生班级 == student.学生班级,
        沃林学生基本信息表.学生姓名 == student.学生姓名
    ).first()
    if db_student:
        raise HTTPException(status_code=400, detail=f"班级{student.学生班级}已存在姓名{student.学生姓名}的学生")

    # 转换为数据库模型对象
    db_student = 沃林学生基本信息表(
        学生班级=student.学生班级,
        学生姓名=student.学生姓名,
        籍贯=student.籍贯,
        毕业院校=student.毕业院校,
        专业=student.专业,
        入学时间=student.入学时间,
        毕业时间=student.毕业时间,
        学历=student.学历,
        顾问编号=student.顾问编号,
        年龄=student.年龄,
        性别=student.性别
    )

    # 写入数据库
    db.add(db_student)
    db.commit()
    db.refresh(db_student)
    return db_student


# 1.2 根据学生编号查询基本信息
@app.get("/student/basic/{student_id}", tags=["学生基本信息管理"], response_model=学生基本信息创建,summary=["查询学生信息"])
def get_student_basic(student_id: int, db: Session = Depends(get_db)):
    db_student = db.query(沃林学生基本信息表).filter(沃林学生基本信息表.学生编号 == student_id).first()
    if not db_student:
        raise HTTPException(status_code=404, detail=f"学生编号{student_id}不存在")
    return db_student


# 1.3 分页查询所有学生基本信息
@app.get("/student/basic", tags=["学生基本信息管理"], response_model=List[学生基本信息创建],summary=["查询学生所有信息"])
def get_all_student_basic(
        skip: int = 0,  # 跳过前n条（默认0）
        limit: int = 10,  # 最多查n条（默认10）
        db: Session = Depends(get_db)
):
    students = db.query(沃林学生基本信息表).offset(skip).limit(limit).all()
    return students


# 1.4 根据学生编号更新基本信息
@app.put("/student/basic/{student_id}", tags=["学生基本信息管理"], response_model=学生基本信息创建,summary=["更改学生信息"])
def update_student_basic(
        student_id: int,
        student_update: 学生基本信息更新,
        db: Session = Depends(get_db)
):
    db_student = db.query(沃林学生基本信息表).filter(沃林学生基本信息表.学生编号 == student_id).first()
    if not db_student:
        raise HTTPException(status_code=404, detail=f"学生编号{student_id}不存在")

    # 只更新前端传了的字段
    if student_update.学生班级:
        db_student.学生班级 = student_update.学生班级
    if student_update.籍贯:
        db_student.籍贯 = student_update.籍贯
    if student_update.毕业院校:
        db_student.毕业院校 = student_update.毕业院校
    if student_update.专业:
        db_student.专业 = student_update.专业
    if student_update.毕业时间:
        db_student.毕业时间 = student_update.毕业时间
    if student_update.学历:
        db_student.学历 = student_update.学历
    if student_update.顾问编号:
        db_student.顾问编号 = student_update.顾问编号
    if student_update.年龄:
        db_student.年龄 = student_update.年龄
    if student_update.性别:
        db_student.性别 = student_update.性别

    db.commit()
    db.refresh(db_student)
    return db_student


# 1.5 根据学生编号删除基本信息（级联删除从表数据，需确保数据库外键已配置on delete cascade）
@app.delete("/student/basic/{student_id}", tags=["学生基本信息管理"],summary=["删除学生信息"])
def delete_student_basic(student_id: int, db: Session = Depends(get_db)):
    db_student = db.query(沃林学生基本信息表).filter(沃林学生基本信息表.学生编号 == student_id).first()
    if not db_student:
        raise HTTPException(status_code=404, detail=f"学生编号{student_id}不存在")

    # 删除主表数据（从表数据会自动级联删除，需数据库表已配置外键级联）
    db.delete(db_student)
    db.commit()
    return {"message": f"学生编号{student_id}的基本信息已删除"}


# ================================= 2. 学生考核成绩表接口 =================================
# 2.1 新增考核成绩
@app.post("/student/score", tags=["学生考核成绩管理"], response_model=学生考核成绩创建,summary=["新增学生信息"])
def create_student_score(
        score: 学生考核成绩创建,
        db: Session = Depends(get_db)
):
    # 先检查学生是否存在
    db_student = db.query(沃林学生基本信息表).filter(沃林学生基本信息表.学生编号 == score.学生编号).first()
    if not db_student:
        raise HTTPException(status_code=404, detail=f"学生编号{score.学生编号}不存在，无法添加成绩")

    # 转换为数据库模型
    db_score = 沃林学生考核成绩表(
        学生编号=score.学生编号,
        考核序次=score.考核序次,
        分数=score.分数
    )

    db.add(db_score)
    db.commit()
    db.refresh(db_score)
    return db_score


# 2.2 根据学生编号查询考核成绩
@app.get("/student/score/{student_id}", tags=["学生考核成绩管理"], response_model=List[学生考核成绩创建],summary=["查询学生信息"])
def get_student_score(student_id: int, db: Session = Depends(get_db)):
    scores = db.query(沃林学生考核成绩表).filter(沃林学生考核成绩表.学生编号 == student_id).all()
    if not scores:
        raise HTTPException(status_code=404, detail=f"学生编号{student_id}暂无考核成绩")
    return scores
# 2.4 全量查询考核成绩（支持分页）
@app.get("/student/score", tags=["学生考核成绩管理"], response_model=List[学生考核成绩创建],summary=["查询所有学生信息"])
def get_all_student_score(
        skip: int = 0,
        limit: int = 100,
        db: Session = Depends(get_db)
):
    scores = db.query(沃林学生考核成绩表).offset(skip).limit(limit).all()
    return scores


# ================================= 3. 学生考勤记录表接口 =================================
# 3.1 新增考勤记录
@app.post("/student/attendance", tags=["学生考勤记录管理"], response_model=学生考勤记录创建,summary=["新增学生信息"])
def create_student_attendance(
        attendance: 学生考勤记录创建,
        db: Session = Depends(get_db)
):
    # 检查学生是否存在
    db_student = db.query(沃林学生基本信息表).filter(沃林学生基本信息表.学生编号 == attendance.学生编号).first()
    if not db_student:
        raise HTTPException(status_code=404, detail=f"学生编号{attendance.学生编号}不存在，无法添加考勤")

    db_attendance = 沃林学生考勤记录表(
        学生编号=attendance.学生编号,
        考核时间=attendance.考核时间,
        补录标记=attendance.补录标记
    )

    db.add(db_attendance)
    db.commit()
    db.refresh(db_attendance)
    return db_attendance


# 3.2 根据学生编号查询考勤记录
@app.get("/student/attendance/{student_id}", tags=["学生考勤记录管理"], response_model=List[学生考勤记录创建],summary=["查询学生信息"])
def get_student_attendance(student_id: int, db: Session = Depends(get_db)):
    attendances = db.query(沃林学生考勤记录表).filter(沃林学生考勤记录表.学生编号 == student_id).all()
    if not attendances:
        raise HTTPException(status_code=404, detail=f"学生编号{student_id}暂无考勤记录")
    return attendances
# 3.4 全量查询考勤记录（支持分页）
@app.get("/student/attendance", tags=["学生考勤记录管理"], response_model=List[学生考勤记录创建])
def get_all_student_attendance(
        skip: int = 0,
        limit: int = 100,
        db: Session = Depends(get_db)
):
    attendances = db.query(沃林学生考勤记录表).offset(skip).limit(limit).all()
    return attendances


# ================================= 4. 学生就业信息表接口 =================================
# 4.1 新增就业信息（续接断层部分）
@app.post("/student/employment", tags=["学生就业信息管理"], response_model=学生就业信息创建,summary=["新增学生信息"])
def create_student_employment(
        employment: 学生就业信息创建,
        db: Session = Depends(get_db)
):
    # 检查学生是否存在
    db_student = db.query(沃林学生基本信息表).filter(沃林学生基本信息表.学生编号 == employment.学生编号).first()
    if not db_student:
        raise HTTPException(status_code=404, detail=f"学生编号{employment.学生编号}不存在，无法添加就业信息")

    # 检查该学生是否已存在就业信息（避免重复添加，可根据实际需求调整）
    db_employment = db.query(沃林学生就业信息表).filter(沃林学生就业信息表.学生编号 == employment.学生编号).first()
    if db_employment:
        raise HTTPException(status_code=400, detail=f"学生编号{employment.学生编号}已存在就业信息，无需重复添加")

    # 转换为数据库模型对象
    db_employment = 沃林学生就业信息表(
        学生编号=employment.学生编号,
        就业开放时间=employment.就业开放时间,
        OFFER下发时间=employment.OFFER下发时间,
        就业公司名称=employment.就业公司名称,
        就业薪资=employment.就业薪资
    )

    db.add(db_employment)
    db.commit()
    db.refresh(db_employment)
    return db_employment

# 4.4 全量查询就业信息（支持分页）
@app.get("/student/employment", tags=["学生就业信息管理"], response_model=List[学生就业信息创建])
def get_all_student_employment(
        skip: int = 0,
        limit: int = 100,
        db: Session = Depends(get_db)
):
    employments = db.query(沃林学生就业信息表).offset(skip).limit(limit).all()
    return employments

# 4.2 根据学生编号查询就业信息
@app.get("/student/employment/{student_id}", tags=["学生就业信息管理"], response_model=学生就业信息创建,summary=["查询学生信息"])
def get_student_employment(student_id: int, db: Session = Depends(get_db)):
    db_employment = db.query(沃林学生就业信息表).filter(沃林学生就业信息表.学生编号 == student_id).first()
    if not db_employment:
        raise HTTPException(status_code=404, detail=f"学生编号{student_id}暂无就业信息")
    return db_employment


# 4.3 根据学生编号更新就业信息（如薪资调整、公司变更等）
@app.put("/student/employment/{student_id}", tags=["学生就业信息管理"], response_model=学生就业信息创建,summary=["更新学生信息"])
def update_student_employment(
        student_id: int,
        employment_update: 学生就业信息创建,  # 复用创建模型（也可单独定义更新模型，只保留可修改字段）
        db: Session = Depends(get_db)
):
    db_employment = db.query(沃林学生就业信息表).filter(沃林学生就业信息表.学生编号 == student_id).first()
    if not db_employment:
        raise HTTPException(status_code=404, detail=f"学生编号{student_id}暂无就业信息，无法更新")

    # 只更新前端传了的字段（避免覆盖原有有效数据）
    if employment_update.就业开放时间:
        db_employment.就业开放时间 = employment_update.就业开放时间
    if employment_update.OFFER下发时间:
        db_employment.OFFER下发时间 = employment_update.OFFER下发时间
    if employment_update.就业公司名称:
        db_employment.就业公司名称 = employment_update.就业公司名称
    if employment_update.就业薪资:
        db_employment.就业薪资 = employment_update.就业薪资

    db.commit()
    db.refresh(db_employment)
    return db_employment


# 4.4 根据学生编号删除就业信息
@app.delete("/student/employment/{student_id}", tags=["学生就业信息管理"],summary=["删除学生信息"])
def delete_student_employment(student_id: int, db: Session = Depends(get_db)):
    db_employment = db.query(沃林学生就业信息表).filter(沃林学生就业信息表.学生编号 == student_id).first()
    if not db_employment:
        raise HTTPException(status_code=404, detail=f"学生编号{student_id}暂无就业信息，无法删除")

    db.delete(db_employment)
    db.commit()
    return {"message": f"学生编号{student_id}的就业信息已删除"}


# -------------------------- 启动服务 --------------------------
if __name__ == '__main__':
    uvicorn.run('studentApi:app', host='localhost', port=8011, reload=True)